import { CharacterConfig } from "./types/CharacterConfig";
import { ResourceManager } from "./core/ResourceManager";
import { SpeechManager } from "./core/SpeechManager";
import { AnimationManager } from "./core/AnimationManager";
import { CharacterRenderer } from "./core/CharacterRenderer";
import { AnimationPresets } from "./core/AnimationPresets";

/**
 * PixiJS角色插件
 *
 * 使用组合模式，将不同功能模块组合在一起
 * 提供完整的角色动画、语音、外观管理功能
 */
export class PixiCharacter {
  /** 角色配置参数 */
  private config: CharacterConfig;

  /** 资源管理器，负责纹理加载和缓存 */
  private resourceManager: ResourceManager;

  /** 语音管理器，负责语音合成功能 */
  private speechManager: SpeechManager;

  /** 动画管理器，负责动画执行和控制 */
  private animationManager: AnimationManager;

  /** 角色渲染器，负责PixiJS渲染和变换 */
  private renderer: CharacterRenderer;

  /** 动画预设，提供预定义的动画效果 */
  private animationPresets: AnimationPresets;

  constructor(container: HTMLElement, config: CharacterConfig = {}) {
    // 合并配置参数，设置默认值
    this.config = {
      width: 400,
      height: 300,
      backgroundColor: 0x87ceeb,
      ...config,
    };

    // 初始化各个管理器
    this.resourceManager = new ResourceManager();
    this.speechManager = new SpeechManager({
      onSpeechStart: this.config.onSpeechStart,
      onSpeechEnd: this.config.onSpeechEnd,
      onError: this.config.onError,
    });
    this.animationManager = new AnimationManager({
      onAnimationStart: this.config.onAnimationStart,
      onAnimationEnd: this.config.onAnimationEnd,
    });
    this.renderer = new CharacterRenderer(
      container,
      {
        width: this.config.width!,
        height: this.config.height!,
        backgroundColor: this.config.backgroundColor!,
      },
      this.resourceManager
    );
    this.animationPresets = new AnimationPresets(this.animationManager);

    // 初始化角色
    this.init();
  }

  /**
   * 初始化角色外观
   */
  private async init() {
    try {
      const {
        body,
        clothes,
        hat,
        leftHand,
        rightHand,
        leftHandPosition,
        rightHandPosition,
        onError,
      } = this.config;
      if (body) await this.renderer.loadBody(body, onError);
      if (clothes) await this.renderer.loadClothes(clothes, onError);
      if (hat) await this.renderer.loadHat(hat, onError);
      if (leftHand)
        await this.renderer.loadLeftHand(leftHand, leftHandPosition, onError);
      if (rightHand)
        await this.renderer.loadRightHand(
          rightHand,
          rightHandPosition,
          onError
        );
    } catch (error) {
      this.config.onError?.(`初始化失败: ${error}`);
    }
  }

  /**
   * 通用代理方法 - 从实例中获取方法并绑定上下文
   */
  private createProxy<T extends object>(instance: T, methodName: keyof T) {
    return (instance[methodName] as Function).bind(instance);
  }

  /**
   * 动画代理方法 - 为动画预设创建代理
   */
  private createAnimationProxy(methodName: keyof AnimationPresets) {
    return (o?: any) =>
      (this.animationPresets[methodName] as Function)(
        this.renderer.getCharacter(),
        o
      );
  }

  // 动画方法 - 使用代理模式
  get wave() {
    return this.createAnimationProxy("wave");
  }
  get jump() {
    return this.createAnimationProxy("jump");
  }
  get spin() {
    return this.createAnimationProxy("spin");
  }
  get bounce() {
    return this.createAnimationProxy("bounce");
  }
  get shake() {
    return this.createAnimationProxy("shake");
  }
  get scale() {
    return this.createAnimationProxy("scale");
  }
  get move() {
    return this.createAnimationProxy("move");
  }

  stop(): void {
    this.animationManager.stop();
  }

  reset(): void {
    this.stop();
    this.renderer.reset();
  }

  // 语音方法 - 使用通用代理
  get speak() {
    return this.createProxy(this.speechManager, "speak");
  }
  get stopSpeaking() {
    return this.createProxy(this.speechManager, "stopSpeaking");
  }
  get isSpeaking() {
    return this.createProxy(this.speechManager, "isSpeaking");
  }

  // 外观方法 - 使用通用代理
  get setBody() {
    return this.createProxy(this.renderer, "loadBody");
  }
  get setClothes() {
    return this.createProxy(this.renderer, "loadClothes");
  }
  get setHat() {
    return this.createProxy(this.renderer, "loadHat");
  }
  get setLeftHand() {
    return this.createProxy(this.renderer, "loadLeftHand");
  }
  get setRightHand() {
    return this.createProxy(this.renderer, "loadRightHand");
  }
  get setHandPosition() {
    return this.createProxy(this.renderer, "setHandPosition");
  }
  get getHandPosition() {
    return this.createProxy(this.renderer, "getHandPosition");
  }

  // 变换方法 - 使用通用代理
  get setPosition() {
    return this.createProxy(this.renderer, "setPosition");
  }
  get setScale() {
    return this.createProxy(this.renderer, "setScale");
  }
  get setRotation() {
    return this.createProxy(this.renderer, "setRotation");
  }

  // 状态方法 - 使用通用代理
  get isAnimating() {
    return this.createProxy(this.animationManager, "isAnimating");
  }
  get getPosition() {
    return this.createProxy(this.renderer, "getPosition");
  }
  get getScale() {
    return this.createProxy(this.renderer, "getScale");
  }
  get getRotation() {
    return this.createProxy(this.renderer, "getRotation");
  }

  // 资源方法
  async preload(paths: string[]): Promise<void> {
    try {
      await this.resourceManager.preload(paths);
    } catch (error) {
      this.config.onError?.(`资源预加载失败: ${error}`);
    }
  }

  async preloadAll(assets: string[]): Promise<void> {
    if (!assets?.length) {
      console.warn("预加载资源列表为空");
      return;
    }
    await this.preload(assets);
  }

  get getCacheStatus() {
    return this.createProxy(this.resourceManager, "getCacheStatus");
  }

  // 生命周期方法
  destroy(): void {
    this.stop();
    this.stopSpeaking();
    this.resourceManager.clearCache();
    this.renderer.destroy();
  }

  // 高级访问方法 - 使用通用代理
  get getApp() {
    return this.createProxy(this.renderer, "getApp");
  }
  get getContainer() {
    return this.createProxy(this.renderer, "getCharacter");
  }
  // 性能监控
  get performance() {
    // 返回帧率，内存
    let lastTime = performance.now();
    let frameCount = 0;
    let fps = 0;
    return {
      getFps: () => {
        const currentTime = performance.now();
        frameCount++;
        const deltaTime = currentTime - lastTime;
        if (deltaTime >= 1000) {
          fps = Math.round((frameCount * 1000) / deltaTime);
          lastTime = currentTime;
          frameCount = 0;
        }
        return fps;
      },
      getMemory: () => {
        const memory = (performance as any).memory;
        if (!memory) {
          return {
            totalJSHeapSize: 0,
            usedJSHeapSize: 0,
            jsHeapSizeLimit: 0,
          };
        }
        return {
          totalJSHeapSize: memory.totalJSHeapSize,
          usedJSHeapSize: memory.usedJSHeapSize,
          jsHeapSizeLimit: memory.jsHeapSizeLimit,
        };
      },
    };
  }
}

export type { CharacterConfig } from "./types/CharacterConfig";
